﻿#region

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Reflection;
using ylyfDataCommon.Exceptions;
using ylyfDataEntityConverter.Common;

#endregion

namespace ylyfDataEntityConverter.GenerticEntityConverter
{
    public class DataEntityConverter<T> : EntityConverter<T> where T : new()
    {
        private readonly Dictionary<string, KeyValuePair<string, PropertyInfo>> CustomEntity =
            new Dictionary<string, KeyValuePair<string, PropertyInfo>>();

        private readonly Dictionary<string, PropertyInfo> entityFieldNameDic = new Dictionary<string, PropertyInfo>();

        public DataEntityConverter()
        {
            var Ttype = typeof(T);
            if (typeof(IDictionary).IsAssignableFrom(Ttype))
            {
                if (Ttype == typeof(Dictionary<string, object>))
                {
                    currentEntityType = EntityType.Dictionary;
                    return;
                }
                throw new ClassNotSuportedInThisConverterException();
            }
            if (Ttype.IsPrimitive || Ttype == typeof(string) || Ttype.IsEnum || Ttype == typeof(Guid))
            {
                currentEntityType = EntityType.Primitive;
                return;
            }
            var types = Ttype.GetProperties();
            foreach (var propertyInfo in types) //初始化模糊引擎，加载大小写忽略匹配缓存
            {
                string propName = propertyInfo.Name;
                if (propertyInfo.GetCustomAttributes(typeof(EntityConverterIgnoreAttribute), false).Length > 0)
                    continue;
                if (propertyInfo.GetCustomAttributes(typeof(DataColumnNameAttribute), false).Length > 0)
                {
                    var tmpname = ((DataColumnNameAttribute)
                        propertyInfo.GetCustomAttributes(typeof(DataColumnNameAttribute), false)[0]).ColumnName;
                    if (!string.IsNullOrWhiteSpace(tmpname))
                        propName = tmpname;
                }
                if (entityFieldNameDic.ContainsKey(propName.ToLower()))
                {
                    PropertyInfo pname = entityFieldNameDic[propName.ToLower()];
                    entityFieldNameDic.Remove(propName.ToLower());
                    entityFieldNameDic[propName.ToLower()] = pname;
                    entityFieldNameDic[propName] = propertyInfo;
                }
                else
                {
                    entityFieldNameDic[propName.ToLower()] = propertyInfo;
                }
            }
            currentEntityType = EntityType.Standard;
        }

        private EntityType currentEntityType { get; }

        public List<T> RetriveEntity(DataTable resultTable)
        {
            if (resultTable.Rows.Count <= 0)
                return null;
            //分流处理方式
            switch (currentEntityType)
            {
                case EntityType.Standard:
                {
                    return RetriveStandardEntity(resultTable, InitColumn(resultTable));
                }
                case EntityType.Dictionary:
                {
                    return RetriveDictionary(resultTable, InitColumn(resultTable));
                }
                case EntityType.Primitive:
                {
                    return RetrivePrimitive(resultTable);
                }
            }
            return null;
        }

        /// <summary>
        ///     生成字典
        /// </summary>
        /// <param name="table">数据表</param>
        /// <param name="colList">列数据</param>
        /// <returns></returns>
        private List<T> RetriveDictionary(DataTable table, List<DataColumn> colList)
        {
            List<T> t = new List<T>();

            foreach (DataRow row in table.Rows)
            {
                T tobj = new T();
                object obj = tobj;
                Dictionary<string, object> dic = (Dictionary<string, object>) obj;
                foreach (DataColumn column in colList)
                    try
                    {
                        dic.Add(column.ColumnName,
                            TypeDescriptor.GetConverter(column.DataType).ConvertFrom(row[column].ToString()));
                    }
                    catch
                    {
                    }
                t.Add(tobj);
            }
            return t;
        }

        /// <summary>
        ///     单对象获取机制
        /// </summary>
        /// <param name="table">数据表</param>
        /// <returns></returns>
        private List<T> RetrivePrimitive(DataTable table)
        {
            List<T> entity = new List<T>();
            foreach (DataRow row in table.Rows)
                try
                {
                    entity.Add((T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(row[0].ToString()));
                }
                catch (Exception)
                {
                }
            return entity;
        }


        /// <summary>
        ///     普通对象处理机制
        /// </summary>
        /// <param name="table">数据表</param>
        /// <param name="columns">列数据</param>
        /// <returns></returns>
        private List<T> RetriveStandardEntity(DataTable table, List<DataColumn> columns)
        {
            List<T> lst = new List<T>();
            foreach (DataRow row in table.Rows)
            {
                T entity = new T();
                foreach (DataColumn col in columns)
                {
                    string str = col.ColumnName;
                    PropertyInfo prop = null;
                    if (entityFieldNameDic.ContainsKey(str.ToLower()))
                        prop = entityFieldNameDic[str.ToLower()];
                    if (prop == null && entityFieldNameDic.ContainsKey(str))
                        prop = entityFieldNameDic[str];
                    if (prop == null || !prop.CanWrite) continue;
                    try
                    {
                        prop.SetValue(entity, TypeDescriptor.GetConverter(prop.PropertyType)
                            .ConvertFrom(row[str].ToString()), null);
                    }
                    catch
                    {
                    }
                }
                lst.Add(entity);
            }
            return lst;
        }

        /// <summary>
        ///     生成列数据
        /// </summary>
        /// <param name="resultTable">结果表</param>
        /// <returns></returns>
        private List<DataColumn> InitColumn(DataTable resultTable)
        {
            //处理DataTable的列和列类型读入缓存
            List<DataColumn> colList = new List<DataColumn>();
            foreach (DataColumn column in resultTable.Columns) //将列名读入缓存
                try
                {
                    colList.Add(column);
                }
                catch
                {
                }
            return colList;
        }
    }

    internal enum EntityType
    {
        Standard = 0,
        Dictionary = 1,
        Primitive = 2
    }
}